package za.co.green;
 
import java.applet.Applet;
import java.awt.Color;
import java.awt.Graphics;
import java.awt.Image;
import java.awt.RenderingHints;
import java.awt.event.KeyEvent;
import java.awt.event.KeyListener;
import java.util.ArrayList;
import java.util.Hashtable;
import java.util.Random;
 

public class AutoGenMaze extends Applet implements KeyListener 
{
    private Image dobleBuffer;
    private Graphics myGraphics;
 
    int cordX = 30;
    int cordY = 30;
    
    ArrayList<Integer> maze_passageWallHolder = new ArrayList<Integer>();
    
    int gameState = 0;
    
    final int player_triangle_baseSize = 30;//30
    
    final int player_triangle_pan_positions = 4;
    
    final int player_triangle_pan_rate = 0;
    
    final int field_max_width = ( player_triangle_baseSize+8 )*22;
    final int field_max_height = ( player_triangle_baseSize+8 )*22;
    
    final int player_triangle_movement = 4;
    
    final int field_extraMoveSpace = 8 + player_triangle_baseSize;
    
    final int cell_count_w = 11;
	
    final int cell_count_h = 11;
	
    final int cell_count = ( cell_count_w*cell_count_h ) - 1;// using 0 based
    
    int player_triangle_pan_currentPosition = 0;
    
    int player_triangle_pointOffset_X_3 = 0;
    int player_triangle_pointOffset_Y_3 = 0;
    
    int player_triangle_pointOffset_X_2 = 0;
    int player_triangle_pointOffset_Y_2 = 0;
    
    int player_triangle_pointOffset_X_1 = 0;
    int player_triangle_pointOffset_Y_1 = 0;
    
 
    public void init() 
    {
    	try
    	{
	    	setName("Auto Maze Gen game");
	    	
	    	setSize(field_max_width, field_max_height); 
	    	
	    	setVisible(true); 
	 
	        addKeyListener(this);
	        
	        gameState++;
	        
	        maze_passageWallHolder = genMaze ();
	 
	        dobleBuffer = createImage(getWidth(), getHeight());
	        myGraphics = dobleBuffer.getGraphics();
	 
	        drawImages();
    	}
    	catch (Exception e)
    	{
    		throw new RuntimeException("init ERROR ::"+e.getMessage());
    	}
    }
 
    @Override
    public void update(Graphics g) {
        
        drawImages();
        
        g.drawImage(dobleBuffer, 0, 0, this);        
    }
 
    public void drawImages() {
    	
    	myGraphics.setColor(Color.white);
    	
    	myGraphics.clearRect(0, 0, field_max_width, field_max_height);
    	
    	myGraphics.setColor(Color.black);
    	
    	for (int i = 0; i < field_max_width; i+=(( field_extraMoveSpace )*2))
    	{
    		myGraphics.drawLine(i, 0, i, field_max_height);
    	}
    	
    	for (int i = 0; i < field_max_height; i+=(( field_extraMoveSpace )*2))
    	{
    		myGraphics.drawLine(0, i, field_max_width, i);
    	}
    	
    	// draw passages (cell*10)+WALL_TYPE
    	
    	myGraphics.setColor(Color.white);
    	
    	for (int i = 0 ; i < maze_passageWallHolder.size(); i++)
    	{
    		int cellWallcombo = maze_passageWallHolder.get(i);
    		
    		int wall = 0;
        	int currentCell = 0;
        	
        	int cell_x = 0;
        	
        	int cell_y = 0;
        	
        	if (cellWallcombo < 10)
        	{
        		wall = cellWallcombo;
        	}
        	else
        	{
        		wall = cellWallcombo % 10;
        		
        		currentCell = (cellWallcombo-wall)  / 10;
        	}
        	
        	// calc where cell is and paint that wall
        	
        	cell_x = (currentCell % cell_count_w ) + 1;
        	
        	cell_y = (currentCell / cell_count_h ) + 1;
        	
        	//( field_extraMoveSpace )*2)
        	
        	switch (wall)
        	{
    	    	case 1:
    	    		//myGraphics.setColor(Color.red);
    	    			myGraphics.drawLine( 
								( ( field_extraMoveSpace * 2) * cell_x ) - ( field_extraMoveSpace * 2) , // 1 X
								
								( ( field_extraMoveSpace * 2) * cell_y ) - ( field_extraMoveSpace * 2),  // 1 Y
								
								( ( field_extraMoveSpace * 2) * cell_x ) - ( field_extraMoveSpace * 2),  // 2 X
								
								( ( field_extraMoveSpace * 2) * cell_y )  							 );  // 2 Y
    	    			//myGraphics.setColor(Color.white);
    	    			break ;
    	    	case 2:
	    	    		//myGraphics.setColor(Color.red);
	    	    		myGraphics.drawLine( 
								( ( field_extraMoveSpace * 2) * cell_x ) - ( field_extraMoveSpace * 2) , // 1 X
								
								( ( field_extraMoveSpace * 2) * cell_y ) - ( field_extraMoveSpace * 2),  // 1 Y
								
								( ( field_extraMoveSpace * 2) * cell_x ) ,  // 2 X
								
								( ( field_extraMoveSpace * 2) * cell_y ) - ( field_extraMoveSpace * 2));  // 2 Y
	    	    		//myGraphics.setColor(Color.white);
    	    			break ;
    	    	case 3:
    	    		//myGraphics.setColor(Color.red);
    	    		myGraphics.drawLine( 
							( ( field_extraMoveSpace * 2) * cell_x )  , // 1 X
							
							( ( field_extraMoveSpace * 2) * cell_y ) - ( field_extraMoveSpace * 2),  // 1 Y
							
							( ( field_extraMoveSpace * 2) * cell_x )  ,  // 2 X
							
							( ( field_extraMoveSpace * 2) * cell_y )  							 );  // 2 Y
    	    		//myGraphics.setColor(Color.white);
    	    			break ;
    	    	case 4:
    	    		myGraphics.drawLine( 
							( ( field_extraMoveSpace * 2) * cell_x ) - ( field_extraMoveSpace * 2) , // 1 X
							
							( ( field_extraMoveSpace * 2) * cell_y ) ,  // 1 Y
							
							( ( field_extraMoveSpace * 2) * cell_x ) ,  // 2 X
							
							( ( field_extraMoveSpace * 2) * cell_y ) );  // 2 Y
    	    			break ;
        	}
        	
    	}
    	gameState++;
    	
    	myGraphics.setColor(Color.black);
    	
    	int[] xPoints = {cordX + player_triangle_pointOffset_X_1, 
    			
    					(cordX + player_triangle_baseSize) + player_triangle_pointOffset_X_2, 
    			
    					( (cordX + ( player_triangle_baseSize * 2 ) ) + player_triangle_pointOffset_X_3)
    					
    	} ;//  .   .    .
    	
    	
    	int[] yPoints = {( cordY+(player_triangle_baseSize * 4) ) + player_triangle_pointOffset_Y_1, 
    			
    					( cordY + (player_triangle_baseSize * 2 ) ) + player_triangle_pointOffset_Y_2, 
    					
    					( cordY+(player_triangle_baseSize * 4) ) + player_triangle_pointOffset_Y_3
    	
    	};
    	
    	
    	
    	myGraphics.drawPolygon(xPoints, yPoints, 3);
    	
    	
    	
    }
 
     
    public void keyPressed(KeyEvent ke) {
        switch (ke.getKeyCode()) {
            
            case KeyEvent.VK_RIGHT: {
                
            	
            	switch (player_triangle_pan_currentPosition)
            	{
            	case 0:
            		player_triangle_pan_currentPosition = 1;
            		
            		player_triangle_pointOffset_X_3 = - (player_triangle_baseSize*2);// - 2 len
            	    player_triangle_pointOffset_Y_3 = 0;// 
            	    
            	    player_triangle_pointOffset_X_2 = player_triangle_baseSize;// + 1 len
            	    player_triangle_pointOffset_Y_2 = player_triangle_baseSize;// + 1 len
            	    
            	    player_triangle_pointOffset_X_1 = 0;// + 1 len
            	    player_triangle_pointOffset_Y_1 = -(player_triangle_baseSize*2);// - 2 len
            	    
            	    break;
            	    
            	case 1:
            		
            		player_triangle_pan_currentPosition = 2;
            		
            		player_triangle_pointOffset_X_3 = -(player_triangle_baseSize*2);
            	    player_triangle_pointOffset_Y_3 = -(player_triangle_baseSize*2);
            	    
            	    player_triangle_pointOffset_X_2 = 0;
            	    player_triangle_pointOffset_Y_2 = (player_triangle_baseSize*2);
            	    
            	    player_triangle_pointOffset_X_1 = (player_triangle_baseSize*2);
            	    player_triangle_pointOffset_Y_1 = -(player_triangle_baseSize*2);
            	    
            	    break;
            	    
            	case 2:
            		
            		player_triangle_pan_currentPosition = 3;
            		
            		player_triangle_pointOffset_X_3 = 0;
            	    player_triangle_pointOffset_Y_3 = -(player_triangle_baseSize*2);
            	    
            	    player_triangle_pointOffset_X_2 = -player_triangle_baseSize;
            	    player_triangle_pointOffset_Y_2 = player_triangle_baseSize;
            	    
            	    player_triangle_pointOffset_X_1 = (player_triangle_baseSize*2);
            	    player_triangle_pointOffset_Y_1 = 0;
            	    
            	    break;
            	    
            	case 3:
            		
            		player_triangle_pan_currentPosition = 0;
            		
            		player_triangle_pointOffset_X_3 = 0;
            	    player_triangle_pointOffset_Y_3 = 0;
            	    
            	    player_triangle_pointOffset_X_2 = 0;
            	    player_triangle_pointOffset_Y_2 = 0;
            	    
            	    player_triangle_pointOffset_X_1 = 0;
            	    player_triangle_pointOffset_Y_1 = 0;
            	    
            	    break;
            	    
            	case 4:
            		
            		player_triangle_pan_currentPosition = 0;
            		
            		player_triangle_pointOffset_X_3 = 0;
            	    player_triangle_pointOffset_Y_3 = 0;
            	    
            	    player_triangle_pointOffset_X_2 = 0;
            	    player_triangle_pointOffset_Y_2 = 0;
            	    
            	    player_triangle_pointOffset_X_1 = 0;
            	    player_triangle_pointOffset_Y_1 = 0;
            	    
            	    break;
            	    
            	case 5:
            		
            		player_triangle_pan_currentPosition = 2;
            		
            		player_triangle_pointOffset_X_3 = -(player_triangle_baseSize*2);
            	    player_triangle_pointOffset_Y_3 = -(player_triangle_baseSize*2);
            	    
            	    player_triangle_pointOffset_X_2 = 0;
            	    player_triangle_pointOffset_Y_2 = (player_triangle_baseSize*2);
            	    
            	    player_triangle_pointOffset_X_1 = (player_triangle_baseSize*2);
            	    player_triangle_pointOffset_Y_1 = -(player_triangle_baseSize*2);
            	    
            	    break;
            	}
            	
            	
            }
            break;
 
           
            case KeyEvent.VK_LEFT: {
               
            	
            	
            	switch (player_triangle_pan_currentPosition)
            	{
            	case 0:
            		player_triangle_pan_currentPosition = 4;
            		
            		player_triangle_pointOffset_X_3 = 0;
            	    player_triangle_pointOffset_Y_3 = -(player_triangle_baseSize*2);
            	    
            	    player_triangle_pointOffset_X_2 = -player_triangle_baseSize;
            	    player_triangle_pointOffset_Y_2 = player_triangle_baseSize;
            	    
            	    player_triangle_pointOffset_X_1 = player_triangle_baseSize*2;
            	    player_triangle_pointOffset_Y_1 = 0;
            	    
            	    break;
            	    
            	case 1:
            		
            		player_triangle_pan_currentPosition = 0;
            		
            		player_triangle_pointOffset_X_3 = 0;
            	    player_triangle_pointOffset_Y_3 = 0;
            	    
            	    player_triangle_pointOffset_X_2 = 0;
            	    player_triangle_pointOffset_Y_2 = 0;
            	    
            	    player_triangle_pointOffset_X_1 = 0;
            	    player_triangle_pointOffset_Y_1 = 0;
            	    
            	    break;
            	    
            	case 2:
            		
            		player_triangle_pan_currentPosition = 1;
            		
            		player_triangle_pointOffset_X_3 = - (player_triangle_baseSize*2);// - 2 len
            	    player_triangle_pointOffset_Y_3 = 0;// 
            	    
            	    player_triangle_pointOffset_X_2 = player_triangle_baseSize;// + 1 len
            	    player_triangle_pointOffset_Y_2 = player_triangle_baseSize;// + 1 len
            	    
            	    player_triangle_pointOffset_X_1 = 0;// + 1 len
            	    player_triangle_pointOffset_Y_1 = -(player_triangle_baseSize*2);// - 2 len
            	    
            	    break;
            	    
            	case 3:
            		
            		player_triangle_pan_currentPosition = 2;
            		
            		player_triangle_pointOffset_X_3 = -(player_triangle_baseSize*2);
            	    player_triangle_pointOffset_Y_3 = -(player_triangle_baseSize*2);
            	    
            	    player_triangle_pointOffset_X_2 = 0;
            	    player_triangle_pointOffset_Y_2 = (player_triangle_baseSize*2);
            	    
            	    player_triangle_pointOffset_X_1 = (player_triangle_baseSize*2);
            	    player_triangle_pointOffset_Y_1 = -(player_triangle_baseSize*2);
            	    
            	    break;
            	    
            	case 4:
            		
            		player_triangle_pan_currentPosition = 2;
            		
            		player_triangle_pointOffset_X_3 = -(player_triangle_baseSize*2);
            	    player_triangle_pointOffset_Y_3 = -(player_triangle_baseSize*2);
            	    
            	    player_triangle_pointOffset_X_2 = 0;
            	    player_triangle_pointOffset_Y_2 = (player_triangle_baseSize*2);
            	    
            	    player_triangle_pointOffset_X_1 = (player_triangle_baseSize*2);
            	    player_triangle_pointOffset_Y_1 = -(player_triangle_baseSize*2);
            	    
            	    break;
            	    
            	case 5:
            		
            		player_triangle_pan_currentPosition = 0;
            		
            		player_triangle_pointOffset_X_3 = 0;
            	    player_triangle_pointOffset_Y_3 = 0;
            	    
            	    player_triangle_pointOffset_X_2 = 0;
            	    player_triangle_pointOffset_Y_2 = 0;
            	    
            	    player_triangle_pointOffset_X_1 = 0;
            	    player_triangle_pointOffset_Y_1 = 0;
            	    
            	    break;
            	}
            	
            	
            	
            }
            break;
 
            
            case KeyEvent.VK_DOWN: {
                
                switch (player_triangle_pan_currentPosition)
            	{
            	case 0:
            		if ((cordY + player_triangle_movement+player_triangle_baseSize*4) <= field_max_height)
            			cordY +=player_triangle_movement;
            		
            		break;
            	    
            	case 1:
            		if ((cordX - player_triangle_movement) >= 0)
            			cordX -=player_triangle_movement;
            		break;
            	    
            	case 2:
            		if ((cordY - player_triangle_movement + player_triangle_baseSize*2) >= 0)
            			cordY -=player_triangle_movement;
            	    break;
            	    
            	case 3:
            		if ((cordX + player_triangle_movement + player_triangle_baseSize*2) <= field_max_width-1)
            			cordX +=player_triangle_movement;
            	    break;
            	    
            	case 4:
            		if ((cordX + player_triangle_movement + player_triangle_baseSize*2) <= field_max_width-1)
            			cordX +=player_triangle_movement;
            	    break;
            	    
            	case 5:
            		if ((cordX - player_triangle_movement) >= 0)
            			cordX -=player_triangle_movement;
            	    break;
            	}
                
                
            }
            break;
 
            
            case KeyEvent.VK_UP: {
               
            	
            	switch (player_triangle_pan_currentPosition)
            	{
            	case 0:
            		if ((cordY - player_triangle_movement + player_triangle_baseSize*2 ) >= 0)
            			cordY -=player_triangle_movement;
            		break;
            	    
            	case 1:
            		if ((cordX + player_triangle_movement + player_triangle_baseSize*2) <= field_max_width-1)
            			cordX +=player_triangle_movement;
            		break;
            	    
            	case 2:
            		if ((cordY + player_triangle_movement + player_triangle_baseSize*4) <= field_max_height)
            			cordY +=player_triangle_movement;
            	    break;
            	    
            	case 3:
            		if ((cordX - player_triangle_movement ) >= 0)
            			cordX -=player_triangle_movement;
            	    break;
            	    
            	case 4:
            		if ((cordX - player_triangle_movement) >= 0)
            			cordX -=player_triangle_movement;
            	    break;
            	    
            	case 5:
            		if ((cordX + player_triangle_movement + player_triangle_baseSize*2) <= field_max_width-1)
            			cordX +=player_triangle_movement;
            	    break;
            	}
            }
            break;
 
        }
        
        repaint();
 
 
    }
 
    
    public void keyTyped(KeyEvent ke) {
    }
 
    
    public void keyReleased(KeyEvent ke) {
    	
    }
    
    private ArrayList<Integer> genMaze ()
    {
    	ArrayList<Integer> maze_cellHolder = new ArrayList<Integer>();
    	
    	ArrayList<Integer> maze_cellWallHolder = new ArrayList<Integer>();
    	
    	ArrayList<Integer> maze_passageWallHolder = new ArrayList<Integer>();
    	
    	int randomWallCell = 0;
    	
    	int [] tempcellWalls = new int[4];
    	
    	maze_cellHolder.add(randomWallCell);
    	
    	tempcellWalls  = find_cellWalls (randomWallCell);
    	
    	for (int i = 0 ; i < 4 ; i++)
		{
			if (tempcellWalls[i] == 1)
			{
				int ourWall = (randomWallCell*10) + (i+1);
				
				maze_cellWallHolder.add(ourWall);
			}
		}
    	
    	Random ranGen = new Random();
    	int randomSelectedWall = 0;
    	int randomWall = 0;
    	
    	while (maze_cellWallHolder.size() > 0)
    	{
    		randomSelectedWall = ranGen.nextInt(maze_cellWallHolder.size()) + 1;
    		
    		randomWall = maze_cellWallHolder.get(randomSelectedWall-1);
    		
    		randomWallCell = findCellOverWall(randomWall);
    		
    		if (maze_cellHolder.contains(randomWallCell))
    		{
    			
    			maze_cellWallHolder.remove(randomSelectedWall-1);
    		}
    		else 
    		{
    			maze_passageWallHolder.add(randomWall);
    			
    			maze_cellHolder.add(randomWallCell);
    			
    			tempcellWalls = find_cellWalls(randomWallCell);
    			
    			for (int i = 0 ; i < 4 ; i++)
    			{
    				if (tempcellWalls[i] == 1)
    				{
    					int ourWall = (randomWallCell*10) + (i+1);
    					
    					maze_cellWallHolder.add(ourWall);
    				}
    			}
    		}
    	}
    	
    	if (maze_passageWallHolder != null && maze_passageWallHolder.size() > 0)
    	{
    		return maze_passageWallHolder;
    	}
    	
    	return null;
    	
    }
    
 // need to id the type of cell, get walls 
	
	//  0  1  2  3  4  5  6  7  8  9 10
	// 11 12 13 14 15 16 17 18 19 20 21
	// 22 23 24 25 26 27 28 29 30 31 32
	// 33 34 35 36 37 38 39 40 41 42 43
	// 44
	// 55
	// 66
	// 77
	// 88
	// 99 100 101 102 103 104 105 106 107 108 109
	//110 111 112 113 114 115 116 117 118 119 120
	//
	
	 /*
    0 0 1 1 = Cor L U
    0 1 1 1 = Sid L
    1 0 1 1 = sid U
    0 1 0 1 = Cor L D
    1 1 1 1 = Middle
    1 0 0 1 = Cor R U
    1 1 0 1 = Sid R
    1 1 1 0 = sid D
    1 1 0 0 = Cor R D
    */
    
    private int[] find_cellWalls (int cell)
    {
    	/*if (cell > cell_count_w*cell_count_h - 1)
    	{
    		// BOOOOOM
    		return new int [] {0,0,0,0};
    	}*/
    	
    	// our probs 
    	
    	
    	// L T R B
    	if (cell == 0 )
    	{
    		return new int [] {0,0,1,1};// ok 1
    	}
    	else if (cell == ( cell_count_w*cell_count_h)-1  )
    	{
    		return new int [] {1,1,0,0}; // ok 9
    	}
    	else if (cell == ( cell_count_w*cell_count_h-1 )  - (cell_count_w-1) )
    	{
    		return new int [] {0,1,1,0};// ok 4
    	}
    	else if (cell == ( cell_count_w - 1 ))
    	{
    		return new int [] {1,0,0,1};// ok 6
    	}
    	else if ( (cell % cell_count_w ) == 0)
    	{
    		return new int [] {0,1,1,1};// ok 2
    	}
    	else if (cell < cell_count_w-1)
    	{
    		return new int [] {1,0,1,1};// ok 3
    	}
    	else if (( (cell+1) % cell_count_w ) == 0)
    	{
    		return new int [] {1,1,0,1};// ok 7
    	}
    	else if ( ( cell < ( cell_count_w*cell_count_h - 1) ) && (cell > ( cell_count_w*cell_count_h-1 )  - (cell_count_w-1) ) )
    	{
    		return new int [] {1,1,1,0};// ok 8
    	}
    	else
    	{
    		return new int [] {1,1,1,1};// ok 5
    	}
    	
    }
    
    
    private int findCellOverWall (int wallCell)
    {
    	// need to unpack 'omit last int'
    	
    	int wall = 0;
    	int currentCell = 0;
    	
    	
    	
    	if (wallCell < 10)
    	{
    		wall = wallCell;
    	}
    	else
    	{
    		wall = wallCell % 10;
    		
    		currentCell = (wallCell-wall)  / 10;
    	}
    	
    	
    	// 1 == -1
    	// 2 == -w
    	// 3 == +1
    	// 4 == +w
    	
    	switch (wall)
    	{
	    	case 1:
	    		
	    			return currentCell - 1;
	    	case 2:
	    		
	    			return currentCell - cell_count_w;
	    	case 3:
	    		
	    			return currentCell + 1;
	    	case 4:
	    		
				return currentCell + cell_count_w;
    	}
    	
    	return 0;
    }
    
    
}